/*->c.vxwimp */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"


#include "h.wos"
#include "h.main"
#include "h.ram"
#include "h.mym"
#include "h.trans"
#include "h.file"
#include "h.term"

#include "h.pr"


#include "h.vtwimp"


#include "h.vxdef"

#include "h.vxcol"
#include "h.vxedit"

#include "h.vxkey"
#include "h.vxbuff"
#include "h.vxterm"
#include "h.mxterm"
#include "h.vxasm"
#include "h.vxsend"
#include "h.vxprint"

#include "h.vxwimp"




/***************************************************************************/
/*
 Code to handle VX terminal sprite
*/
/*****************************************************************************/

char * vxtsprite=NULL;

int vxusemode;

int vxnotrans;       /* don't have to scale/col trans when plotting sprite */

int               vxscalefactors;                 /* sprite scaling active */
sprite_factors    vxscaleblock;
sprite_pixtrans * vxpixtrans;
char              vxpixtable[16];

int               vxwidth=40;


/*****************************************************************************/


char vxchars00[512*2*10];   /* buffer to hold mode  0 characters */
char vxchars18[512*2*20];   /* buffer to hold mode 18 characters */


int vxloadcharfile(char * name,char * dest,int height)
{
 FILE        * fp;
 sprite_area   spa;
 sprite_header sphdr;
 int           i;
 int           j;
 int           word;
 char          filename[128];


 sprintf(filename,"%s.%s",path(HSYRD),name);

 fp=fopen(filename,"rb");
 if(fp)
 {
  fread((char*)(&spa)+4,1,sizeof(sprite_area)-4,fp);

  for(i=0;i<256;i++)
  {
   fread(&sphdr,1,sizeof(sprite_header),fp);
   for(j=0;j<height;j++)
   {
    fread(&word,1,sizeof(int),fp);
    *dest++=(char)word;
    *dest++=(char)(word>>4);
   }
  }

  fclose(fp);
  return(1);
 }
 return(0);
}



void vxsetcharsize(vxscreen * vsc)
{
 vsc->oscharx=((VXBDX*vsc->zoom.mul)/vsc->zoom.div) & maskx;
 if(vsc->oscharx<2*deltax) vsc->oscharx=2*deltax;
 vsc->oschary=((VXBDY*vsc->zoom.mul)/vsc->zoom.div) & masky;
 if(vsc->oschary<2*deltay) vsc->oschary=2*deltay;
}



void vxsetscales(vxscreen * vsc)
{
 vsc->notrans=vxnotrans;
 vsc->scaleblock=vxscaleblock;
 vsc->scalefactors=vxscalefactors;

 vxsetcharsize(vsc);

 if(vsc->zoom.mul!=vsc->zoom.div)
 {
  vsc->notrans=0;

  if(!vxscalefactors)
  {
   vsc->scalefactors=1;
   vsc->scaleblock.xmag=VXDX;
   vsc->scaleblock.xdiv=VXBDX;
   vsc->scaleblock.ymag=VXDY;
   vsc->scaleblock.ydiv=VXBDY;
  }
  else
  {
   vsc->scaleblock.xmag*=VXDX;
   vsc->scaleblock.xdiv*=VXBDX;
   vsc->scaleblock.ymag*=VXDY;
   vsc->scaleblock.ydiv*=VXBDY;
  }
 }
/* else
 {
  vsc->oscharx=VXBDX;
  vsc->oschary=VXBDY;
 } */
}



void vxcreatetermsprite(void)
{
 int       size;
 int       swidth;
 int       sheight;
 int       mustscalex=0;
 int       mustscaley=0;
 int       mustcoltrans=0;
 int       i;
 int       spln2bpp;

 vxnotrans=1;
 vxpixtrans=(sprite_pixtrans *)(-1);
 vxscalefactors=0;

 if(vxopen)
 {
  /* sort things out from mode etc. */

  size=sizeof(sprite_area)+sizeof(sprite_header);

  if(gcharsizey==16) sheight=20;
  else 
  {
   if(gcharsizey!=8) mustscaley=1;
   sheight=10;
  }

  if(gcharsizex!=8) mustscalex=1;

  spln2bpp=ln2bpp;

  if(ln2bpp==5)
  {
   swidth=48*vxwidth;
   if(gcharsizey==16) vxusemode=MX329090;
   else               vxusemode=MX329045;
  }
  else
  if(ln2bpp==4)
  {
   swidth=24*vxwidth;
   if(gcharsizey==16) vxusemode=MX169090;
   else               vxusemode=MX169045;
  }
  else
  if(ln2bpp==3)
  {
   swidth=12*vxwidth;
   if(gcharsizey==16) vxusemode=21;
   else               vxusemode=15;
  }
  else
  {
   if(ln2bpp!=2)      
   {
    mustcoltrans=1;
    spln2bpp=2;
   }

   swidth=6*vxwidth;
   if(gcharsizey==16) vxusemode=20;
   else               vxusemode=12;
  }

  size+=swidth*sheight;


  if(vxtsprite) flex_extend((flex_ptr)&vxtsprite,size);
  else          flex_alloc((flex_ptr)&vxtsprite,size);

  sprite_area_initialise((sprite_area *)vxtsprite,size);


  /* up to here, swidth is bytes, in the line below it is pixels */

  swidth=(swidth*8)/(1<<spln2bpp);


  report(sprite_create((sprite_area *)vxtsprite,"TERMSP",0,
                                                   swidth,sheight,vxusemode));

  if(mustscalex || mustscaley)
  {
   vxscalefactors=1;

   if(mustscalex)
   {
    vxscaleblock.xmag=gcharsizex;
    vxscaleblock.xdiv=8;
   }
   else
   {
    vxscaleblock.xmag=1;
    vxscaleblock.xdiv=1;
   }

   if(mustscaley)
   {
    vxscaleblock.ymag=gcharsizey;
    vxscaleblock.ydiv=8;
   }
   else
   {
    vxscaleblock.ymag=1;
    vxscaleblock.ydiv=1;
   }
   vxnotrans=0;
  }

  if(mustcoltrans)
  {
   wimp_palettestr wpal;
   wimp_readpalette(&wpal);
   selecttable(vxusemode,(int*)&wpal,-1,(int*)-1,vxpixtable);
   vxpixtrans=vxpixtable;
   vxnotrans=0;
  }

  vxsetscales(vscr); /* main terminal window */
  for(i=0;i<MAXBUFF;i++) if(vxbuff[i].vsc) vxsetscales(vxbuff[i].vsc);
 }
}


void vxtrashtermsprite(void)
{
 if(vxtsprite)
   flex_free((flex_ptr)&vxtsprite);
}



void vxinit(void)
{
 vxloadcharfile("C_VX00",&vxchars00[0],10);
 vxloadcharfile("C_VXX00",&vxchars00[256*2*10],10);
 vxloadcharfile("C_VX18",&vxchars18[0],20);
 vxloadcharfile("C_VXX18",&vxchars18[256*2*20],20);
}



/*****************************************************************************/
/* save screen as sprite */

int vxsavescreenspsub(char * filename,vxscreen * vsc)
{
 FILE * fp;

 sprite_area   spa;
 sprite_header sph;
 int           palsize;
 int           y;
 int           spwidth;
 int           xhilo;
 int           temp;


 sprite_header  *  tspa=(sprite_header*)
                           (vxtsprite+(((sprite_area *)vxtsprite)->sproff));
 char           *  image=((char*)tspa)+tspa->image;
 sprite_id spid;   


/* wimp_palettestr wpal; */


 if((fp=ropen(filename,"wb"))==NULL) return(0);

 spa.number=1;
 spa.sproff=sizeof(sprite_area);

/* palsize=16*2*sizeof(int);  */
 palsize=0;

 sph.mode=vxusemode;
 sph.image=sizeof(sprite_header)+palsize;
 sph.mask=sph.image;
 memset(sph.name,0,12);
 strcpy(sph.name,"screen");

 xhilo=40;
 if(vxusemode==15 || vxusemode==21) xhilo*=2;
 else
 if(vxusemode==MX169090 || vxusemode==MX169045) xhilo*=4;
 else
 if(vxusemode==MX329090 || vxusemode==MX329045) xhilo*=8;


 temp=xhilo*3;
 temp=(temp>>1);

 tspa->width=temp-1;

 spwidth=temp*4;


 sph.width=tspa->width;
 sph.height=(tspa->height+1)*24-1;

 sph.lbit=0;
 sph.rbit=31;

 sph.next=sph.image+(sph.height+1)*(sph.width+1)*sizeof(int);
 spa.freeoff=sph.next+sizeof(sprite_area);


 rwrite(&spa.number,sizeof(sprite_area)-sizeof(int),1,fp);
 rwrite(&sph,sizeof(sprite_header),1,fp);


/*
 wimp_readpalette(&wpal);

 for(y=0;y<16;y++)
 {
  wpal.c[y].bytes.gcol=0;
  rwrite(&wpal.c[y],sizeof(int),1,fp);
  rwrite(&wpal.c[y],sizeof(int),1,fp);
 }
 */

 spid.tag=sprite_id_addr;
 spid.s.addr=tspa;

 for(y=vsc->start;y<vsc->height;y++)
 {
  if(vxinvert) vxinvertline(&(vsc->tvbuf[y][0]));

  if(vxusemode>MXNEWMODE)
  {
   if(vxusemode==MX329090)
   {
    vxline329090S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX329045)
   {
    vxline329045S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX169090)
   {
    vxline169090S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX169045)
   {
    vxline169045S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
  }
  else
  if(vxusemode>15)
  {
   if(vxusemode==20)
   {
    vxline18S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
   else
   {
    vxline23S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
  }
  else
  {
   if(vxusemode==12)
   {
    vxline00S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   }
   else
   {
    vxline15S(&(vsc->tvbuf[y][0]),image,xhilo,spwidth);
   } 
  }
  
  /* save data */

  rwrite(image,(tspa->height+1)*(tspa->width+1)*sizeof(int),1,fp);

  if(vxinvert) vxinvertline(&(vsc->tvbuf[y][0]));
 }

 savetypeclose(fp,filename);
 return(1);
}




int vxsavescreensp(char * filename)
{
 return(vxsavescreenspsub(filename,vscr));
}




/*****************************************************************************/
/*
 Code to handle Viewdata wimp interface
*/
/*****************************************************************************/



#define NLINE    0x0
#define RDATA    0x1
#define RDRAW    0x2



void redrawvxsub(wimp_redrawstr * redrawstr,int flags,vxscreen * vsc)
{
 int ox;
 int oy;
 int xlo;
 int xhi;
 int ylo;
 int yhi;
 int y;
 int temp;
 int xhilo;
 int xplot;
 int yplot;
 int spwidth;
 int attr;
 int oldattr;
 int atrf=-1;
 int oldrlo;
 int oldrhi;

 sprite_header  *  tspa=(sprite_header*)
                           (vxtsprite+(((sprite_area *)vxtsprite)->sproff));
 char           *  image=((char*)tspa)+tspa->image;
 sprite_id spid;   


 vxflashflash(isprinter?0:vsc->flashphase);
 vxflashflash2(isprinter?0:vsc->flashphase);
 vxsetgrid(vsc->pixelgrid);


 ox=redrawstr->box.x0-redrawstr->scx;
 oy=redrawstr->box.y1-redrawstr->scy;

 spid.tag=sprite_id_addr;
 spid.s.addr=tspa;

 oldattr=-1;
 oldrlo=oldrhi=0;

 ylo=((oy-redrawstr->g.y1)/VXDY);

 temp=oy-redrawstr->g.y0;
 yhi=temp/VXDY;
 if(yhi*VXDY!=temp) yhi++;

 if(yhi>vsc->height) yhi=vsc->height;

 yplot=oy-ylo*VXDY;


 for(y=ylo;y<yhi;y++)
 {
  yplot-=VXDY;
  attr=vsc->attr[y];

  if(flags==RDATA)
  {                                
   if(vsc->rlo[y]==vsc->rhi[y]) continue;  /* !!!!! be careful */

   if(vsc->rlo[y]!=oldrlo || vsc->rhi[y]!=oldrhi)
   {
    oldrlo=vsc->rlo[y];
    oldrhi=vsc->rhi[y];

    oldattr=-1;
   }
  }
  else
  if(flags==NLINE) vsc->rlo[y]=vsc->rhi[y]=0;


  if(oldattr)
  {
   xlo=(redrawstr->g.x0-ox)/VXDX;

   temp=redrawstr->g.x1-ox;
   xhi=temp/VXDX;
   if((xhi*VXDX)!=temp) xhi++;

   if(xhi>40) xhi=40;

   if(flags==RDATA)
   {
    if(xlo<oldrlo) xlo=oldrlo;
    if(xhi>oldrhi) xhi=oldrhi;
   }


   xhilo=xhi-xlo;

   if(vxusemode==15 || vxusemode==21) xhilo*=2;
   else
   if(vxusemode==MX169090 || vxusemode==MX169045) xhilo*=4;
   else
   if(vxusemode==MX329090 || vxusemode==MX329045) xhilo*=8;

   temp=xhilo*3;
   temp=(temp>>1);

   if(xhilo & 1)
   {
    temp++;
    tspa->rbit=15;
   }
   else
   {
    tspa->rbit=31;
   }

   tspa->width=temp-1;

   spwidth=temp*4;

   xplot=ox+xlo*VXDX;
  }

  oldattr=0;


  if(xlo>=xhi) continue;

  if(ttvx>=xlo && ttvx<=xhi && y==ttvy) atrf=attr>0;

  if(vxpinvert) vxinvertline(&(vsc->tvbuf[y][0]));


  if(vxusemode>MXNEWMODE)
  {
   if(vxusemode==MX329090)
   {
    vxline329090S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX329045)
   {
    vxline329045S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX169090)
   {
    vxline169090S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
   else
   if(vxusemode==MX169045)
   {
    vxline169045S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
  }
  else
  if(vxusemode>15)
  {
   if(vxusemode==20)
   {
    vxline18S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
   else
   {
    vxline23S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
  }
  else
  {
   if(vxusemode==12)
   {
    vxline00S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   }
   else
   {
    vxline15S(&(vsc->tvbuf[y][xlo]),image,xhilo,spwidth);
   } 
  }

  if(isprinter)
  {
   wimp_palettestr wpal;
   char pixtable[256];

   if(vxusemode==12 || vxusemode==20)
   {
    wimp_readpalette(&wpal);
    selecttable(vxusemode,(int*)&wpal,-1,(int*)-1,pixtable);
   }
   else
    selecttable(vxusemode,0,-1,(int*)-1,pixtable);

   sprite_put_scaled((sprite_area *)vxtsprite,&spid,0,xplot,yplot,
                    vsc->scalefactors?&(vsc->scaleblock):NULL,pixtable);

   if(vxpinvert) vxinvertline(&(vsc->tvbuf[y][0]));
  }
  else
  {
   if(vsc->notrans)
              sprite_put_given((sprite_area *)vxtsprite,&spid,0,xplot,yplot);
   else
              sprite_put_scaled((sprite_area *)vxtsprite,&spid,0,xplot,yplot,
                    vsc->scalefactors?&(vsc->scaleblock):NULL,vxpixtrans);


   if(vsc==vscr)
   {
    vxredbox0l(redrawstr,xlo,xhi,y);
    vxredbox1l(redrawstr,xlo,xhi,y);
   }
  }

   /* a continue comes here ... */
 } 
     
 if(atrf>=0 && !vxmovecurs)
 {
  if(vxcurs && vxcursphase && vsc==vscr && !isprinter)
  {
   /* draw cursor */
   seteorcol(0,7);
   if(vedit)
   {
    bbc_rectangle(ox+ttvx*VXDX,oy-(ttvy+1)*VXDY,
                                                 VXDX-deltax,VXDY-deltay);
   }
   else if(vxblock)
   {
    bbc_rectanglefill(ox+ttvx*VXDX,oy-(ttvy+1)*VXDY,
                                                 VXDX-deltax,VXDY-deltay);
   }
   else
   {
    bbc_move(ox+ttvx*VXDX,oy-(ttvy+1)*VXDY+deltay);
    bbc_draw(ox+(ttvx+1)*VXDX-deltax,oy-(ttvy+1)*VXDY+deltay);
   }
  }
 }
}



void vxredraw(void)
{
 wimp_redrawstr redrawstr;
 int            more;

 redrawstr.w=ewindow;

 wimp_redraw_wind(&redrawstr,&more);
 while(more)
 {
  redrawvxsub(&redrawstr,RDRAW,vscr);
  wimp_get_rectangle(&redrawstr,&more);
 }
}



/* called to redraw any areas of the screen that we have changed */

void vxdoredraw(vxscreen * vsc)
{
 wimp_redrawstr redrawstr;
 int more;
 int xlo;
 int xhi;
 int ylo;
 int yhi;
 int y;

 getw(whandle[VDATA]);

 xlo=((x0-bx)/VXDX);
 xhi=((x1-bx)/VXDX)+1;
 ylo=((by-y1)/VXDY);
 yhi=((by-y0)/VXDY);


 /* scan this area to find area in need of redraw */

 while(1)
 {
  if(vsc->rlo[ylo]!=vsc->rhi[ylo]) break;
  ylo++;
  if(ylo>=yhi) break;
 }

 while(1)
 {
  if(vsc->rlo[yhi]!=vsc->rhi[yhi]) break;
  yhi--;
  if(yhi<=ylo) break;
 }

 if(ylo>yhi) return;


 redrawstr.w=whandle[VDATA];
 redrawstr.box.x0=xlo*VXDX;
 redrawstr.box.x1=xhi*VXDX;
 redrawstr.box.y0=-(yhi+1)*VXDY; 
 redrawstr.box.y1=-(ylo*VXDY);   

 wimp_update_wind(&redrawstr,&more);

 while(more)
 {
  redrawvxsub(&redrawstr,RDATA,vsc);
  wimp_get_rectangle(&redrawstr,&more);
 }


 for(y=ylo;y<=yhi;y++)
 {
  vsc->rlo[y]=vsc->rhi[y]=0;
 }
}





/* called to redraw any areas of the screen that are flashing */

void vxgenflashupdate(vxscreen * vsc)
{
 int xlo;
 int xhi;
 int cxlo;
 int cxhi;
 int rnd1;
 int ylo;
 int yhi;
 int flo;
 int fhi;


 getw(whandle[VDATA]);

 xlo=((x0-bx)/VXDX);
 xhi=(x1-bx);
 rnd1=xhi % VXDX;
 xhi=xhi/VXDX;

 ylo=((by-y1-scy)/VXDY);
 yhi=((by-y0-scy)/VXDY)+1;

 /* scan this area to find area in need of redraw */

 while(ylo<=yhi)
 {

  if(vsc->flo[ylo]!=vsc->fhi[ylo])
  {
   cxlo=xlo;
   cxhi=xhi+rnd1;

   flo=vsc->flo[ylo];
   fhi=vsc->fhi[ylo];
   if(flo<cxlo) flo=cxlo;
   if(fhi>cxhi) fhi=cxhi;
      
   if(flo<fhi)
   {
    vsc->rlo[ylo]=flo;
    vsc->rhi[ylo]=fhi;
    vxpendredraw=1;
   }
  }
  ylo++;
 }
}



void vxsetfocus(void)
{
 setfocus(whandle[VDATA]);
 if(terminalmodeset) terminalmode=1;
}


void vxsetfocusfront(void)
{
 vxsetfocus();
 forward(whandle[VDATA]);
}


void vxclick(void)
{
 if(buttons==2) popvxmain();
 else
 {
  findcaret();
  if(chandle!=whandle[VDATA]) vxsetfocus();
  else                                        /* then... */
  {
   if(vedit) vxedicon();
   else
   {
    switch(buttons)
    {
     case   0x1:             /* double click with adjust */
                vxreplytombx(vscr,whandle[VDATA]);
                break;

     case   0x4:             /* double click with select */
                vxhomecursortomouse();
                break;

     case 0x100:             /* single click with adjust */
                vxsendreturn();
                break;

     case 0x400:             /* single click with select */
                vxsendcursorcode(vscr,whandle[VDATA]);
                break;
                       
    }
   }
  }
 }
}






void vxzero(void)
{
 if(!vxpendredraw)
 {
  if(vxflashtime<zerotime)
  {
   vxflashtime=zerotime+50;
   vxflashphase^=(VXFLASH1+VXFLASH2);
   vscr->flashphase=vxflashphase;
   vxgenflashupdate(vscr);
  }
 }


 if(vxcurs)
 {
  if(vxcurstime<zerotime || vxmovecurs)
  {
   if(vxmovecurs) vxcursphase=1;
   else           vxcursphase^=1;
   vxcurstime=zerotime+50;
   if(vxcursphase || !vxmovecurs)
   {
    vxmarkredraw(vscr,ttvy,ttvx,ttvx);
    vxpendredraw=1;
   }
   vxmovecurs=0;
  }
 }

 if(vxmodded) convertline(vscr,ttvy);
 else
 if(mxmodded) mxconvert(vscr);

 if(vxpendredraw)
 {
  vxdoredraw(vscr);
  vxpendredraw=0;
 }
}



void vxdestroy(void)
{
 if(vxexists)
 {
  vxdefz=vscr->zoom;
  flex_free((flex_ptr)&vscr);
  closedownt(VDATA);
  vxexists=0;
  if(terminalmode==TMODEVT) terminalmode=TMODENUL;
 }
}



void setvxframesize(void)
{
 if(minitel) vxframesize=CEPT2FF;
 else        vxframesize=vxhearsayff?CEPT3FF:HEARSAYFF;
}



int vxcreate(int type)
{
 int handle;

 if(vxexists) return(1);

 vxnewcolourmap();

 if(!vscr)
 {
  if(!flex_alloce((flex_ptr)&vscr,sizeof(vxscreen))) return(0);
 }

 mxreset();
 vxcurs=1;
 viewescflag=0;

 vxdefz.mul=vxdefz.div=1;
 vscr->zoom=vxdefz;

 vscr->flashphase=0;
 vscr->pixelgrid=0;

 if(type==TERMVX)
 {
  handle=createwindowsub(VDATA,transtoken("VDATA"));
  minitel=0;
  vscr->height=24;
  vscr->start=0;
  viewclslo(vscr);
 }
 else
 {
  handle=createwindowsub(VDATA,transtoken("MINITEL"));
  minitel=1;
  vscr->height=25;
  vscr->start=1;
  mxclslo(vscr);
 }

 setvxframesize();
 vxsetcharsize(vscr);
 extent(handle,0,-VXEDYM*vscr->height,VXEDXM*40,0);

 vxexists=1;

 return(1);
}





void vxopenwindows(int new)
{
 int         handle=whandle[VDATA];
 wimp_wstate winds;
 int         height;

 vedit=0;
 vxopen=1;

 vxnewcolourmap();
 vxcreatetermsprite();

 wimp_get_wind_state(handle,&winds);

 if(new)
 {
  winds.o.box.x0=deltax;
  winds.o.box.x1=winds.o.box.x0+40*VXDXM;

  height=vscr->height*VXDYM+2*hscrlbar;

  winds.o.box.y1=screeny-hscrlbar/* -deltay */;
  winds.o.box.y0=winds.o.box.y1-
                            ((height>screeny)?(24*VXDYM):(vscr->height*VXDYM));

  winds.o.y=-vscr->start*VXDYM;
  winds.o.behind=-1;
 }

 wimp_open_wind(&winds.o);

 if(vxkeypad && !whandle[KEYPAD]) vxkeypadopen();

 addzeroevent(VXZERO);
 vxsetfocus();
}




void vxclosewindows(void)
{
 if(vxopen)
 {
  wimp_close_wind(whandle[VDATA]);
  remzeroevent(VXZERO);
  vxtrashtermsprite();
  vxopen=0;
  if(vxkeypad) vxkeypadclose();
  if(vedit)    vxstopedit();
  vxbclosebuffers();
 }
}




/* only called from edit                                */
/* only called on main viewdata window in viewdata mode */

void vxrefreshwindow(int handle,vxscreen * vsc)
{
 int y;
 for(y=0;y<24;y++) convertline(vsc,y);
 refreshwindow(handle);
}




void vxdoallcolourmaps(void)
{
 int i;

 vxdocolourmap(vscr,whandle[VDATA]);

 for(i=0;i<MAXBUFF;i++)
   if(vxbuff[i].vsc) vxdocolourmap(vxbuff[i].vsc,vxbuff[i].handle);
}




void vxpalchange(void)
{
 vxcreatetermsprite();
 if(vxnewcolourmap()) vxdoallcolourmaps();
}



void vxmodechange(void)
{
 vxcreatetermsprite();
 if(vxnewcolourmap()) vxdoallcolourmaps();
}




void vxmenuzoom(int handle,vxscreen * vsc)
{
 vxsetscales(vsc);

 getw(handle);
 extent(handle,0,-VXEDY*(vsc->height),VXEDX*40,0);
 open(handle,x0,y0,x1,y1,scx,scy,bhandle);

 refreshwindow(handle);
}



void vxdozoom(void)
{
 vxmenuzoom(whandle[VDATA],vscr);
}




void vxnewzoom(int mul,int div,vxscreen * vsc,int handle)
{
 if(mul==vsc->zoom.mul && div==vsc->zoom.div) return;

 if(mul*vsc->zoom.div==div*vsc->zoom.mul) return;

 vsc->zoom.mul=mul;
 vsc->zoom.div=div;

 vxsetscales(vsc);

 refreshwindow(handle);
}




void vxsetvarzoomlo(int handle,vxscreen * vsc)
{
 int h;
 int w;
 int xmul;
 int xdiv;
 int ymul;
 int ydiv;

 getw(handle);

 w=(x1-x0)/40;                         /* os units per char */
 h=(y1-y0)/(vsc->height);              /* os units per char */

 xmul=w/deltax;
 if(w % deltax) xmul++;               /* pixels per char        */
 xdiv=(VXBDX/deltax);                 /* pixels per normal char */
                                   
 ymul=h/deltay;
 if(h % deltay) ymul++;               /* pixels per char        */
 ydiv=(VXBDY/deltay);                 /* pixels per normal char */

 if(xmul*ydiv>ymul*xdiv) vxnewzoom(xmul,xdiv,vsc,handle);
 else                    vxnewzoom(ymul,ydiv,vsc,handle);
}



void vxvarzoomsub(int handle,vxscreen * vsc)
{
 getw(handle);
 extent(handle,0,-VXEDY*(vsc->height),VXEDX*40,0);
 open(handle,x0,y0,x1,y1,scx,scy,bhandle);
 vxsetvarzoomlo(handle,vsc);
}


void vxmainvarzoom(void)
{
 vxvarzoomsub(whandle[VDATA],vscr);
}



void openvx(wimp_openstr * wopen)
{
 clipwindow(wopen,1);
 wimp_open_wind(wopen);
 if(vscr->zoom.var) vxsetvarzoomlo(whandle[VDATA],vscr);
}


